package com.mufeng.libs.state

import androidx.annotation.MainThread
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

sealed class StateData<out T> (val time: Long = System.currentTimeMillis()){
    data object Loading : StateData<Nothing>()
    data class Success<out T>(val data: T?) : StateData<T>()
    data class Error(val code: String, val msg: String) : StateData<Nothing>()
}

class ResultBuilder<T>() {
    var loading: (() -> Unit)? = null
        private set
    var success: ((data: T?) -> Unit)? = null
        private set
    var error: ((code: String, msg: String) -> Unit)? = null
        private set

    fun onLoading(block: () -> Unit) {
        loading = block
    }

    fun onSuccess(block: (T?) -> Unit) {
        success = block
    }

    fun onError(block: (code: String, msg: String) -> Unit) {
        error = block
    }
}

typealias StatefulLiveData<T> = LiveData<StateData<T>>
typealias StatefulMutableLiveData<T> = MutableLiveData<StateData<T>>

@MainThread
inline fun <T> StatefulLiveData<T>.observeState(
    owner: LifecycleOwner,
    init: ResultBuilder<T>.() -> Unit
) {
    val result = ResultBuilder<T>().apply(init)

    observe(owner) { state ->
        when (state) {
            is StateData.Loading -> result.loading?.invoke()
            is StateData.Success -> result.success?.invoke(state.data)
            is StateData.Error -> result.error?.invoke(state.code, state.msg)
        }
    }
}